#ifndef RSIM_MAT3X3_H
#define RSIM_MAT3X3_H

/* -------------------------------------------------------------------------- *
 * File: Mat3x3.h                                                             *
 * Authors: Kishor Bhalerao                                                   *
 * Email : kishor8dm@gmail.com                                                *
 * Contributors:                                                              *
 * Email:                                                                     *
 * copyright (c) 2010 Authors.                                                *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify it    *
 * under the terms of the GNU General Public License as published by the Free *
 * Software Foundation, either version 3 of the License, or any later version.*
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details. (http://www.gnu.org/licenses/)                           *
 * -------------------------------------------------------------------------- */

#include "Matrix.h"

namespace RSIM{

template<class T>
class Mat3x3_:public Matrix_<T>{
	public:
		/** Allocate space*/
		Mat3x3_();
		
		/** Allocate space and set each element to val. */
		explicit Mat3x3_(const T& val);
		
		/** Allocate space and copy the array val.Careful, no bound checks. */
		explicit Mat3x3_(const T*val);
		
		/** deep copy */
		Mat3x3_(const Matrix_<T>& M);
		
		void copy(const T *ptr);
		
		/** deep copy */
		Mat3x3_(const Mat3x3_<T>& M);
		
		/** deep copy. */
		void operator=(const Mat3x3_<T>&);
		
		/** deep copy. No validity checks */
		void operator=(const Matrix_<T>&);
		
		/** Create a diagonal matrix with elements v1, v2, and v3*/
		void Diagonal(const T& v1, const T& v2, const T& v3);
};

///////////////////////////////////////////////////////

template <class T>						
void Mat3x3_<T>::operator=(const Mat3x3_<T>& M){
	const T *m = M.Ptr();
	this->data_[0] = m[0];	this->data_[1] = m[1];	this->data_[2] = m[2];
	this->data_[3] = m[3];	this->data_[4] = m[4];	this->data_[5] = m[5];
	this->data_[6] = m[6];	this->data_[7] = m[7];	this->data_[8] = m[8];
}

///////////////////////////////////////////////////////

template <class T>						
void Mat3x3_<T>::operator=(const Matrix_<T>& M){
	const T *m = M.Ptr();
	this->data_[0] = m[0];	this->data_[1] = m[1];	this->data_[2] = m[2];
	this->data_[3] = m[3];	this->data_[4] = m[4];	this->data_[5] = m[5];
	this->data_[6] = m[6];	this->data_[7] = m[7];	this->data_[8] = m[8];
}

///////////////////////////////////////////////////////

template <class T>						
Mat3x3_<T>::Mat3x3_():Matrix_<T>(3,3){}

///////////////////////////////////////////////////////

template <class T>						
Mat3x3_<T>::Mat3x3_(const T& val):Matrix_<T>(3,3,val){}

///////////////////////////////////////////////////////

template <class T>						
Mat3x3_<T>::Mat3x3_(const T *val):Matrix_<T>(3,3,val){}

///////////////////////////////////////////////////////

template <class T>						
Mat3x3_<T>::Mat3x3_(const Matrix_<T>& M):Matrix_<T>(M){}

///////////////////////////////////////////////////////

template <class T>						
Mat3x3_<T>::Mat3x3_(const Mat3x3_<T>& M):Matrix_<T>(M,3,3){}

///////////////////////////////////////////////////////

template <class T>						
void Mat3x3_<T>::copy(const T *ptr){
	this->data_[0]=ptr[0];	this->data_[1]=ptr[1];	this->data_[2]=ptr[2];
	this->data_[3]=ptr[3];	this->data_[4]=ptr[4];	this->data_[5]=ptr[5];
	this->data_[6]=ptr[6];	this->data_[7]=ptr[7];	this->data_[8]=ptr[8];
}

template <class T>
void Mat3x3_<T>::Diagonal(const T& v1, const T& v2, const T& v3){
	this->data_[0]=T(v1);	this->data_[1]=T(0.0);	this->data_[2]=T(0.0);
	this->data_[3]=T(0.0);	this->data_[4]=T(v2);	this->data_[5]=T(0.0);
	this->data_[6]=T(0.0);	this->data_[7]=T(0.0);	this->data_[8]=T(v3);
}

///////////////////////////////////////////////////////

} // namespace RSIM
#endif
